import cv2
import numpy as np
import time
import pyautogui
from pathlib import Path
from app.core.key_board import *

root_dir=Path(__file__).resolve().parent.parent.parent
# region 缩放比例
def found_scale(image_path, image_num=1, threshold=0.8):
    """
    根据传入的图像路径、指定图像序号以及相似度阈值，查找对应图像在屏幕上的位置，并返回匹配时使用的缩放比例。

    参数:
    image_path (str): 要查找并点击的图像文件的路径。
    image_num (int): 指定要点击的匹配图像的序号，默认为1，表示点击第一个匹配到的图像位置，可根据实际需求调整。
    threshold (float): 图像匹配的相似度阈值，默认值为0.8，可根据实际情况调整。
    progress_bar (QProgressBar): 进度条组件，用于显示匹配进度

    返回:
    float: 匹配时使用的缩放比例，如果未找到匹配图像则返回 -1。
    """
    image_path = str(root_dir / image_path)
    # 读取模板图像（要查找的图像）
    template = cv2.imread(image_path, 0)

    # 获取屏幕截图
    screenshot = pyautogui.screenshot()
    screenshot = cv2.cvtColor(np.array(screenshot), cv2.COLOR_RGB2BGR)
    screenshot_gray = cv2.cvtColor(screenshot, cv2.COLOR_BGR2GRAY)

    # 定义缩放比例范围，从 0.5 到 2.0，共 20 个缩放比例
    scales = np.linspace(0.3, 5.0, 1000)

    for _, scale in enumerate(scales):
        resized_template = cv2.resize(template, (int(template.shape[1] * scale), int(template.shape[0] * scale)))
        if resized_template.shape[0] > screenshot_gray.shape[0] or resized_template.shape[1] > screenshot_gray.shape[1]:
            # 如果缩放后的模板图像比屏幕截图大，则跳过此次循环
            continue

        # 进行模板匹配，使用 cv2.TM_CCOEFF_NORMED 方法
        result = cv2.matchTemplate(screenshot_gray, resized_template, cv2.TM_CCOEFF_NORMED)
        # 设置相似度阈值
        locations = np.where(result >= threshold)

        if len(locations[0]) >= image_num:
            return scale  # 找到匹配图像，返回对应的缩放比例

    print(f"根据设置的阈值 {threshold}，在界面上找到的匹配图像数量不足 {image_num} 个，请检查图像或阈值设置。")
    return -1  # 未找到匹配图像，返回 -1
# endregion

# region 点击图像
def click_image(image_path, image_num=1, threshold=0.7, scale=1.0):
    """
    根据传入的图像路径、指定图像序号、相似度阈值以及缩放比例，查找并点击对应图像在屏幕上的位置。

    参数:
    image_path (str): 要查找并点击的图像文件的路径。
    image_num (int): 指定要点击的匹配图像的序号，默认为1，表示点击第一个匹配到的图像位置，可根据实际需求调整。
    threshold (float): 图像匹配的相似度阈值，默认值为0.8，可根据实际情况调整。
    scale (float): 图像的缩放比例，默认值为1.0，表示不进行缩放，可根据实际需求调整。

    """
    positions = find_grid_patterns(image_path=image_path, scale=scale, threshold=threshold)
    if not positions:
            print(f"未找到匹配图像：{image_path} (阈值={threshold})")
            return

    # 计算实际要使用的索引
    max_index = len(positions) - 1
    use_index = min(image_num-1, max_index)  # 保证索引不超过最大可用值
    
    pt = positions[use_index]
    center_x, center_y = (pt[0] + 0.5), (pt[1] + 0.5)

    mouse_click(center_x, center_y)

    time.sleep(0.5)

    # 添加调试信息
    if use_index != image_num-1:
        print(f"警告：请求第{image_num}个匹配项，但只找到{len(positions)}个，已使用最后一个匹配项")
# endregion

# region 等待图像
def wait_image(image_path, threshold=0.7, scale=1.0):
    """
    根据传入的图像路径、相似度阈值以及缩放比例，查找图片是否存在，存在则继续执行，不存在则等待。

    参数:
    image_path (str): 要查找并点击的图像文件的路径。
    threshold (float): 图像匹配的相似度阈值，默认值为0.8，可根据实际情况调整。
    scale (float): 图像的缩放比例，默认值为1.0，表示不进行缩放，可根据实际情况调整。

    """
    while True:
        positions = find_grid_patterns(image_path=image_path, scale=scale, threshold=threshold)
        if len(positions) > 0:
            return
        time.sleep(0.5)
# endregion    

# region 等待多个图像
def wait_many_image(image_paths, threshold=0.7, scale=1.0):
    """
    根据传入的图像路径数组、相似度阈值以及缩放比例，查找数组中任意一个图片是否存在，存在则继续执行，不存在则等待。

    参数:
    image_paths (list): 要查找的图像文件路径的数组或列表。
    threshold (float): 图像匹配的相似度阈值，默认值为0.8，可根据实际情况调整。
    scale (float): 图像的缩放比例，默认值为1.0，表示不进行缩放，可根据实际情况调整。
    """
    while True:
        for image_path in image_paths:
            positions = find_grid_patterns(image_path=image_path, scale=scale, threshold=threshold)
            if len(positions) > 0:
                return
        time.sleep(0.5)
# endregion

# region 等待并点击图像
def wait_click_image(image_path, threshold=0.7, scale=1.0):
    """
    根据传入的图像路径、相似度阈值以及缩放比例，查找图片是否存在，存在则继续执行，不存在则等待。找到图片后，点击图片中心位置。

    参数:
    image_path (str): 要查找并点击的图像文件的路径。
    threshold (float): 图像匹配的相似度阈值，默认值为0.8，可根据实际情况调整。
    scale (float): 图像的缩放比例，默认值为1.0，表示不进行缩放，可根据实际情况调整。

    """
    wait_image(image_path=image_path, threshold=threshold, scale=scale)
    click_image(image_path=image_path, threshold=threshold, scale=scale)
# endregion

# region 判断图像存在
def is_image_now(image_path, threshold=0.7, scale=1.0):
    """
    判断当前界面是否存在指定图片。

    参数:
    image_path (str): 要查找的图像文件的路径。
    threshold (float): 图像匹配的相似度阈值，默认值为0.8，可根据实际情况调整。
    scale (float): 图像的缩放比例，默认值为1.0，表示不进行缩放，可根据实际情况调整。

    返回:
    bool: 如果在当前界面找到指定图片，返回True；否则返回False。
    """
    positions = find_grid_patterns(image_path=image_path, scale=scale, threshold=threshold)
    return len(positions) > 0
# endregion

# region 判断图像存在并点击
def if_exist_click_image(image_path, threshold=0.7, scale=1.0):
    """
    判断当前界面是否存在指定图片，并点击图片。

    参数:
    image_path (str): 要查找并点击的图像文件路径。
    threshold (float): 图像匹配的相似度阈值，默认值为0.8，可根据实际情况调整。
    scale (float): 图像的缩放比例，默认值为1.0，表示不进行缩放，可根据实际情况调整。
    返回:
    bool: 如果在当前界面找到指定图片，返回True，并点击图片；否则返回False。
    """
    positions = find_grid_patterns(image_path=image_path, scale=scale, threshold=threshold)
    if len(positions) > 0:
        pt = positions[0]
        center_x, center_y = (pt[0] + 0.5), (pt[1] + 0.5)
        mouse_click(center_x, center_y)
        return True
    return False
# endregion

# region 记录图像坐标
def find_grid_patterns(image_path, scale=1.0, threshold=0.7, queue=None, start_x=0, start_y=0):
    """
    扫描屏幕并记录规则排列图案的坐标
    
    参数:
    image_path: 模板图像路径
    scale: 图像缩放比例 (默认1.0)
    threshold: 匹配阈值 (默认0.8)
    queue: 存储坐标的列表
    start_x: 扫描起始X坐标 (默认0)
    start_y: 扫描起始Y坐标 (默认0)
    """
    y_image_path = image_path
    image_path = str(root_dir / image_path)
    queue = queue if queue is not None else []
    
    # 获取屏幕尺寸
    screen_width, screen_height = pyautogui.size()
    
    # 新增：立即检查起始坐标有效性
    if start_x < 0 or start_y < 0 or start_x >= screen_width or start_y >= screen_height:
        return queue
    
    # 读取并预处理模板
    template = cv2.imread(image_path, 0)
    if template is None:
        raise ValueError(f"无法读取图像: {image_path}")
    
    # 计算缩放后的尺寸
    h, w = template.shape
    scaled_w = int(w * scale)
    scaled_h = int(h * scale)
    scaled_template = cv2.resize(template, (scaled_w, scaled_h))
    
    # 计算截屏区域尺寸
    region_width = screen_width - start_x
    region_height = screen_height - start_y
    
    # 边界检查（确保区域尺寸有效）
    if region_width <= 0 or region_height <= 0:
        return queue
    
    try:
        # 新增：确保区域参数为整数且符合要求
        region = (int(start_x), int(start_y), int(region_width), int(region_height))
        screenshot = pyautogui.screenshot(region=region)
    except Exception as e:
        print(f"截屏失败: {e}")
        return queue
    
    # 图像处理
    screenshot = cv2.cvtColor(np.array(screenshot), cv2.COLOR_RGB2BGR)
    gray_screen = cv2.cvtColor(screenshot, cv2.COLOR_BGR2GRAY)
    
    # 模板匹配
    res = cv2.matchTemplate(gray_screen, scaled_template, cv2.TM_CCOEFF_NORMED)
    locs = np.where(res >= threshold)
    
    if len(locs[0]) > 0:
        # 转换坐标并排序
        locations = sorted(zip(*locs[::-1]), key=lambda x: (x[1], x[0]))  # 按行优先排序
        
        # 取第一个匹配位置
        best_x, best_y = locations[0]
        
        # 计算实际屏幕坐标
        actual_x = start_x + best_x + scaled_w // 2
        actual_y = start_y + best_y + scaled_h // 2
        # print(f"找到匹配位置: X={actual_x}, Y={actual_y}")
        queue.append((actual_x, actual_y))
        
        # 横向递归：向右扫描
            # 在递归调用时添加额外保护
        new_start_x = start_x + best_x + scaled_w
        if new_start_x > screen_width - scaled_w:  # 预判下次递归是否越界
            new_start_x = max(0, screen_width - scaled_w)
        find_grid_patterns(y_image_path, scale, threshold, queue, new_start_x, start_y)
    else:
        # 纵向递归：换行扫描
        if start_x == 0:
            # 已经处于行首且未找到，结束扫描
            return queue
        else:
            # 换行继续扫描
            last_y=queue[-1][1] if queue else start_y
            new_start_y =last_y
            find_grid_patterns(y_image_path, scale, threshold, queue, 0, new_start_y)
    return queue
# endregion

# region 快速点击图像
def click_one_image(image_path, image_num=1, threshold=0.8, scale=1.0):
    """
    根据传入的图像路径、相似度阈值以及缩放比例，查找并点击对应图像在屏幕上的位置。

    参数:
    image_path (str): 要查找并点击的图像文件的路径。
    threshold (float): 图像匹配的相似度阈值，默认值为0.8，可根据实际情况调整。
    scale (float): 图像的缩放比例，默认值为1.0，表示不进行缩放，可根据实际情况调整。

    """
    # 读取模板图像（要查找的图像）
    template = cv2.imread(image_path, 0)
    template_height, template_width = template.shape[:2]

    # 对模板图像进行缩放
    resized_template = cv2.resize(template, (int(template_width * scale), int(template_height * scale)))
    resized_template_height, resized_template_width = resized_template.shape[:2]

    # 获取屏幕截图
    screenshot = pyautogui.screenshot()
    screenshot = cv2.cvtColor(np.array(screenshot), cv2.COLOR_RGB2BGR)
    screenshot_gray = cv2.cvtColor(screenshot, cv2.COLOR_BGR2GRAY)

    # 进行模板匹配，使用cv2.TM_CCOEFF_NORMED方法，可根据实际换用其他匹配方法
    result = cv2.matchTemplate(screenshot_gray, resized_template, cv2.TM_CCOEFF_NORMED)
    # 设置相似度阈值，这里默认为0.8，可根据实际情况调整
    locations = np.where(result >= threshold)
    if len(locations[0]) >= image_num:
        # 根据传入的image_num取对应位置（序号从1开始，所以减1获取索引位置）
        pt = (locations[1][image_num - 1], locations[0][image_num - 1])
        center_x, center_y = (pt[0] + resized_template_width / 2), (pt[1] + resized_template_height / 2)
        mouse_click(center_x, center_y)
        time.sleep(1)
    else:
        print(f"根据设置的阈值 {threshold}，在界面上找到的匹配图像数量不足 {image_num} 个，请检查图像或阈值设置。")
# endregion